﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Data.OleDb;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;

using PRET.ReportDataDefine.DBData;

namespace PRET.PRETService.Data
{
    public class WinCCDataProcess : IDisposable
    {
        #region WINCC变量
        private readonly static string JCJName = "JCJ";
        // 变量枚举类型
        private enum VariableType { JCJSummaryType = 1, JCJDetailType, JHJDataType, TeamType, WaitingOrderType };
        private readonly static string JHJName = "JHJ";
        private readonly static string[] WaitingVarList = new string[] {
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "WOrderNum1", //待产产品订单号——低位
            "WOrderNum2", //待产产品订单号——中位
            "WOrderNum3", //待产产品订单号——高位
            "WOrderNum4" //待产产品订单号——字母代号
            //"Wcount" //待产产品目标数量
        };
        private readonly static string[] TeamVariableList = new string[]{
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "TeamName1", //当前班组
            //"TeamName2", //当前班组——中位
            //"TeamName3", //当前班组——中位
            //"TeamName4", //当前班组——高位
            "Mixinger1", //混料员工号——低位
            "Mixinger2", //混料员工号——高位
            //"Mixinger3", //混料员工号——中位
            //"Mixinger4", //混料员工号——高位
            "Extruder1", //挤出员工号——低位
            "Extruder2", //挤出员工号——高位
            //"Extruder3", //挤出员工号——中位
            //"Extruder4", //挤出员工号——高位
            "Packer1", //包装员工号——低位
            "Packer2", //包装员工号——高位
            //"Packer3", //包装员工号——中位
            //"Packer4", //包装员工号——高位
            "Qualer1", //质量员工号——低位
            "Qualer2" //质量员工号——高位
            //"Qualer3", //质量员工号——中位
            //"Qualer4" //质量员工号——高位
        };
        private readonly static string[] JCSummaryVariableList = new string[] {
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "OrderNum1", //当前产品订单号——字母代号
            "OrderNum2", //当前产品订单号——高位
            "OrderNum3", //当前产品订单号——中位
            "OrderNum4", //当前产品订单号——低位
            "BalScale1", //1#秤设定比例
            "BalScale2", //2#秤设定比例
            "BalScale3", //3#秤设定比例
            "JTemOff1", //挤出机温度1区允差范围
            "JTemOff2", //挤出机温度2区允差范围
            "JTemOff3", //挤出机温度3区允差范围
            "JTemOff4", //挤出机温度4区允差范围
            "JTemOff5", //挤出机温度5区允差范围
            "JTemOff6", //挤出机温度6区允差范围
            "JTemOff7", //挤出机温度7区允差范围
            "JTemOff8", //挤出机温度8区允差范围
            "JTemOff9", //挤出机温度9区允差范围
            "JTemOff10", //挤出机温度10区允差范围
            "JTemSet1", //挤出机温度1区设定值
            "JTemSet2", //挤出机温度2区设定值
            "JTemSet3", //挤出机温度3区设定值
            "JTemSet4", //挤出机温度4区设定值
            "JTemSet5", //挤出机温度5区设定值
            "JTemSet6", //挤出机温度6区设定值
            "JTemSet7", //挤出机温度7区设定值
            "JTemSet8", //挤出机温度8区设定值
            "JTemSet9", //挤出机温度9区设定值
            "JTemSet10", //挤出机温度10区设定值
            "JMaxRev", //挤出机转速上限
            "JMinRev", //挤出机转速下限
            "JMaxCur", //挤出机电流上限
            "JMinCur", //挤出机电流下限
            "Ia", // 电流1
            "Ib", // 电流2
            "Ic", // 电流3
            "power", // 功率
            "degreeH", // 电表高位
            "degreeL", // 电表低位
            "MaxRZ", //产品熔指上限
            "MinRZ", //产品熔指下限
            "MaxRemn", //产品残余上限
            "MinRemn", //产品残余下限
            "JsProduce" //挤出机生产状态
        };
        private readonly static string[] JCDetailVariableList = new string[] {
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "OrderNum1", //当前产品订单号——字母代号
            "OrderNum2", //当前产品订单号——高位
            "OrderNum3", //当前产品订单号——中位
            "OrderNum4", //当前产品订单号——低位
            "BalRCount1", //1#秤累计下料量实际值
            "BalRCount2", //2#秤累计下料量实际值
            "BalRCount3", //3#秤累计下料量实际值
            "WLJRev", //体积喂料机转速实际值
            "JTemReal1", //挤出机温度1区实际值
            "JTemReal2", //挤出机温度2区实际值
            "JTemReal3", //挤出机温度3区实际值
            "JTemReal4", //挤出机温度4区实际值
            "JTemReal5", //挤出机温度5区实际值
            "JTemReal6", //挤出机温度6区实际值
            "JTemReal7", //挤出机温度7区实际值
            "JTemReal8", //挤出机温度8区实际值
            "JTemReal9", //挤出机温度9区实际值
            "JTemReal10", //挤出机温度10区实际值
            "JRealRev", //挤出机转速实际值
            "JRealCur", //挤出机电流实际值
            "RealRz", //产品熔指实际值
            "RealRemn", //产品残余实际值
            "JsProduce" //挤出机生产状态
        };
        private readonly static string[] JCVariableList = new string[] {
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "OrderNum1", //当前产品订单号——字母代号
            "OrderNum2", //当前产品订单号——高位
            "OrderNum3", //当前产品订单号——中位
            "OrderNum4", //当前产品订单号——低位
            "BalScale1", //1#秤设定比例
            "BalScale2", //2#秤设定比例
            "BalScale3", //3#秤设定比例
            "BalRCount1", //1#秤累计下料量实际值
            "BalRCount2", //2#秤累计下料量实际值
            "BalRCount3", //3#秤累计下料量实际值
            "WLJRev", //体积喂料机转速实际值
            "JTemOff1", //挤出机温度1区允差范围
            "JTemOff2", //挤出机温度2区允差范围
            "JTemOff3", //挤出机温度3区允差范围
            "JTemOff4", //挤出机温度4区允差范围
            "JTemOff5", //挤出机温度5区允差范围
            "JTemOff6", //挤出机温度6区允差范围
            "JTemOff7", //挤出机温度7区允差范围
            "JTemOff8", //挤出机温度8区允差范围
            "JTemOff9", //挤出机温度9区允差范围
            "JTemOff10", //挤出机温度10区允差范围
            "JTemSet1", //挤出机温度1区设定值
            "JTemSet2", //挤出机温度2区设定值
            "JTemSet3", //挤出机温度3区设定值
            "JTemSet4", //挤出机温度4区设定值
            "JTemSet5", //挤出机温度5区设定值
            "JTemSet6", //挤出机温度6区设定值
            "JTemSet7", //挤出机温度7区设定值
            "JTemSet8", //挤出机温度8区设定值
            "JTemSet9", //挤出机温度9区设定值
            "JTemSet10", //挤出机温度10区设定值
            "JTemReal1", //挤出机温度1区实际值
            "JTemReal2", //挤出机温度2区实际值
            "JTemReal3", //挤出机温度3区实际值
            "JTemReal4", //挤出机温度4区实际值
            "JTemReal5", //挤出机温度5区实际值
            "JTemReal6", //挤出机温度6区实际值
            "JTemReal7", //挤出机温度7区实际值
            "JTemReal8", //挤出机温度8区实际值
            "JTemReal9", //挤出机温度9区实际值
            "JTemReal10", //挤出机温度10区实际值
            "JMaxRev", //挤出机转速上限
            "JMinRev", //挤出机转速下限
            "JRealRev", //挤出机转速实际值
            "JMaxCur", //挤出机电流上限
            "JMinCur", //挤出机电流下限
            "JRealCur", //挤出机电流实际值
            "Ia", // 电流1
            "Ib", // 电流2
            "Ic", // 电流3
            "power", // 功率
            "degreeH", // 电表高位
            "degreeL", // 电表低位
            "MaxRZ", //产品熔指上限
            "MinRZ", //产品熔指下限
            "RealRz", //产品熔指实际值
            "MaxRemn", //产品残余上限
            "MinRemn", //产品残余下限
            "RealRemn", //产品残余实际值
            "JsProduce" //挤出机生产状态
        };

        private readonly static string[] JHVariableList = new string[] {
            "ProLine1", //生产线编号——低位
            "ProLine2", //生产线编号——高位
            "OrderNum1", //当前产品订单号——低位
            "OrderNum2", //当前产品订单号——中位
            "OrderNum3", //当前产品订单号——高位
            "OrderNum4", //当前产品订单号——字母代号
            "ZDTemper", //B桶锥度物料实际温度
            "ARealTem", // A桶物料实际温度
            "ABStartT", //A至B桶输送运行状态
            "BHeatST", //B桶加热运行状态
            "BThrowST", //B桶放料包装运行状态
            "UnitPC", // 单包公斤
            "UnitTC", // 放料次数
            "PJobSP", //订单开始指示
            "Ia", // 电流1
            "Ib", // 电流2
            "Ic", // 电流3
            "power", // 功率
            "degree" // 电表
        };

        private readonly static string[] MeterVariableList = new string[] {
            "MeterID", // 电表编号
            "ProLine", // 生产线编号
            "PeakUP", // 峰值单价
            "GenUP", // 平值单价
            "LowUP", // 谷值单价
            "PeakQut", // 峰值电量
            "GenQut", // 平值电量
            "LowQut", // 谷值电量
            "MaxCur", // 最大电流
            "MinCur", // 最小电流
            "MaxLoad" // 最大负荷
        };
        #endregion

        #region SQL
        private readonly static string GET_JCJSUMMARY_VARLIST = "SELECT * FROM [pret].[dbo].[JCJSummaryVariable]" +
            "WHERE [ProLineCode] = '{0}'";
        private readonly static string GET_JCJDETAIL_VARLIST = "SELECT * FROM [pret].[dbo].[JCJDetailVariable]" +
            "WHERE [ProLineCode] = '{0}'";
        private readonly static string GET_JHJDATA_VARLIST = "SELECT * FROM [pret].[dbo].[JHJDataVariable]" +
            "WHERE [ProLineCode] = '{0}'";
        private readonly static string GET_TEAM_VARLIST = "SELECT * FROM [pret].[dbo].[TeamVariable]" +
            "WHERE [ProLineCode] = '{0}'";
        private readonly static string GET_WAITINGORDER_VARLIST = "SELECT * FROM [pret].[dbo].[WaitingOrderVariable]" +
            "WHERE [ProLineCode] = '{0}'";
        private readonly static string INSERT_JCJSUMMARY_VARIABLE = "INSERT INTO [pret].[dbo].[JCJSummaryVariable]" +
           "([ProLineCode],[ProLine1],[ProLine2],[OrderNum1],[OrderNum2],[OrderNum3],[OrderNum4]" +
           ",[BalScale1],[BalScale2],[BalScale3]" +
           ",[JTemOff1],[JTemOff2],[JTemOff3],[JTemOff4],[JTemOff5],[JTemOff6],[JTemOff7],[JTemOff8],[JTemOff9],[JTemOff10]" +
           ",[JTemSet1],[JTemSet2],[JTemSet3],[JTemSet4],[JTemSet5],[JTemSet6],[JTemSet7],[JTemSet8],[JTemSet9],[JTemSet10]" +
           ",[JMaxRev],[JMinRev],[JMaxCur],[JMinCur],[Ia],[Ib],[Ic],[power],[degreeH],[degreeL]" +
           ",[MaxRZ],[MinRZ],[MaxRemn],[MinRemn],[JsProduce]) " +
        "VALUES" +
           "('{0}'" + // <ProLineCode, varchar(10),>
           ",{1}" + // <ProLine1, int,>
           ",{2}" + // <ProLine2, int,>
           ",{3}" + // <OrderNum1, int,>
           ",{4}" + // <OrderNum2, int,>
           ",{5}" + // <OrderNum3, int,>
           ",{6}" + // <OrderNum4, int,>
           ",{7}" + // <BalScale1, int,>
           ",{8}" + // <BalScale2, int,>
           ",{9}" + // <BalScale3, int,>
           ",{10}" + // <JTemOff1, int,>
           ",{11}" + // <JTemOff2, int,>
           ",{12}" + // <JTemOff3, int,>
           ",{13}" + // <JTemOff4, int,>
           ",{14}" + // <JTemOff5, int,>
           ",{15}" + // <JTemOff6, int,>
           ",{16}" + // <JTemOff7, int,>
           ",{17}" + // <JTemOff8, int,>
           ",{18}" + // <JTemOff9, int,>
           ",{19}" + // <JTemOff10, int,>
           ",{20}" + // <JTemSet1, int,>
           ",{21}" + // <JTemSet2, int,>
           ",{22}" + // <JTemSet3, int,>
           ",{23}" + // <JTemSet4, int,>
           ",{24}" + // <JTemSet5, int,>
           ",{25}" + // <JTemSet6, int,>
           ",{26}" + // <JTemSet7, int,>
           ",{27}" + // <JTemSet8, int,>
           ",{28}" + // <JTemSet9, int,>
           ",{29}" + // <JTemSet10, int,>
           ",{30}" + // <JMaxRev, int,>
           ",{31}" + // <JMinRev, int,>
           ",{32}" + // <JMaxCur, int,>
           ",{33}" + // <JMaxCur, int,>
           ",{34}" + // <Ia, int,>
           ",{35}" + // <Ib, int,>
           ",{36}" + // <Ic, int,>
           ",{37}" + // <power, int,>
           ",{38}" + // <degreeH, int,>
           ",{39}" + // <degreeL, int,>
           ",{40}" + // <MaxRZ, int,>
           ",{41}" + // <MinRZ, int,>
           ",{42}" + // <MaxRemn, int,>
           ",{43}" + // <MinRemn, int,>
           ",{44})"; // <JsProduce, int>
        private readonly static string INSERT_JCJDETAIL_VARIABLE = "INSERT INTO [pret].[dbo].[JCJDetailVariable]" +
           "([ProLineCode],[ProLine1],[ProLine2],[OrderNum1],[OrderNum2],[OrderNum3],[OrderNum4]" +
            ",[BalRCount1],[BalRCount2],[BalRCount3],[WLJRev]" +
            ",[JTemReal1],[JTemReal2],[JTemReal3],[JTemReal4],[JTemReal5],[JTemReal6],[JTemReal7],[JTemReal8],[JTemReal9],[JTemReal10]" +
            ",[JRealRev],[JRealCur],[RealRz],[RealRemn],[JsProduce]) " +
        "VALUES" +
           "('{0}'" + // <ProLineCode, varchar(10),>
           ",{1}" + // <ProLine1, int,>
           ",{2}" + // <ProLine2, int,>
           ",{3}" + // <OrderNum1, int,>
           ",{4}" + // <OrderNum2, int,>
           ",{5}" + // <OrderNum3, int,>
           ",{6}" + // <OrderNum4, int,>
           ",{7}" + // <BalRCount1, int,>
           ",{8}" + // <BalRCount2, int,>
           ",{9}" + // <BalRCount3, int,>
           ",{10}" + // <WLJRev, int,>
           ",{11}" + // <JTemReal1, int,>
           ",{12}" + // <JTemReal2, int,>
           ",{13}" + // <JTemReal3, int,>
           ",{14}" + // <JTemReal4, int,>
           ",{15}" + // <JTemReal5, int,>
           ",{16}" + // <JTemReal6, int,>
           ",{17}" + // <JTemReal7, int,>
           ",{18}" + // <JTemReal8, int,>
           ",{19}" + // <JTemReal9, int,>
           ",{20}" + // <JTemReal10, int,>
           ",{21}" + // <JRealRev, int,>
           ",{22}" + // <JRealCur, int,>
           ",{23}" + // <RealRz, int,>
           ",{24}" + // <RealRemn, int,>
           ",{25})";  // <JsProduce, int,>
        private readonly static string INSERT_JHJDATA_VARIABLE = "INSERT INTO [pret].[dbo].[JHJDataVariable]" +
           "([ProLineCode],[ProLine1],[ProLine2],[OrderNum1],[OrderNum2],[OrderNum3],[OrderNum4]" +
            ",[ZDTemper],[ARealTem],[ABStartT],[BHeatST],[BThrowST],[UnitPC],[UnitTC],[PJobSP]" + 
            ",[Ia],[Ib],[Ic],[power],[degree]) " +
        "VALUES" +
           "('{0}'" + // <ProLineCode, varchar(10),>
           ",{1}" + // <ProLine1, int,>
           ",{2}" + // <ProLine2, int,>
           ",{3}" + // <OrderNum1, int,>
           ",{4}" + // <OrderNum2, int,>
           ",{5}" + // <OrderNum3, int,>
           ",{6}" + // <OrderNum4, int,>
           ",{7}" + // <ZDTemper, int,>
           ",{8}" + // <ARealTem, int,>
           ",{9}" + // <ABStartT, int,>
           ",{10}" + // <BHeatST, int,>
           ",{11}" + // <BThrowST, int,>
           ",{12}" + // <UnitPC, int,>
           ",{13}" + // <UnitTC, int,>
           ",{14}" + // <PJobSP, int,>
           ",{15}" + // <Ia, int,>
           ",{16}" + // <Ib, int,>
           ",{17}" + // <Ic, int,>
           ",{18}" + // <power, int,>
           ",{19})"; // <degree, int,>
        private readonly static string INSERT_TEAM_VARIABLE = "INSERT INTO [pret].[dbo].[TeamVariable]" +
           "([ProLineCode],[ProLine1],[ProLine2]" +
            ",[TeamName1],[Mixinger1],[Mixinger2],[Extruder1],[Extruder2],[Packer1],[Packer2],[Qualer1],[Qualer2]) " +
        "VALUES" +
           "('{0}'" + // <ProLineCode, varchar(10),>
           ",{1}" + // <ProLine1, int,>
           ",{2}" + // <ProLine2, int,>
           ",{3}" + // <TeamName1, int,>
           ",{4}" + // <Mixinger1, int,>
           ",{5}" + // <Mixinger2, int,>
           ",{6}" + // <Extruder1, int,>
           ",{7}" + // <Extruder2, int,>
           ",{8}" + // <Packer1, int,>
           ",{9}" + // <Packer2, int,>
           ",{10}" + // <Qualer1, int,>
           ",{11})"; // <Qualer2, int,>
        private readonly static string INSERT_WAITINGORDER_VARIABLE = "INSERT INTO [pret].[dbo].[WaitingOrderVariable]" +
           "([ProLineCode],[ProLine1],[ProLine2]" +
            ",[WOrderNum1],[WOrderNum2],[WOrderNum3],[WOrderNum4]) " +
        "VALUES" +
           "('{0}'" + // <ProLineCode, varchar(10),>
           ",{1}" + // <ProLine1, int,>
           ",{2}" + // <ProLine2, int,>
           ",{3}" + // <WOrderNum1, int,>
           ",{4}" + // <WOrderNum2, int,>
           ",{5}" + // <WOrderNum3, int,>
           ",{6})"; // <WOrderNum4, int,>
        private readonly static string DELETE_JCJSUMMARY_VARIABLE = "DELETE FROM [pret].[dbo].[JCJSummaryVariable] " +
           "WHERE [ProLineCode] = '{0}'";
        private readonly static string DELETE_JCJDETAIL_VARIABLE = "DELETE FROM [pret].[dbo].[JCJDetailVariable] " +
           "WHERE [ProLineCode] = '{0}'";
        private readonly static string DELETE_JHJDATA_VARIABLE = "DELETE FROM [pret].[dbo].[JHJDataVariable] " +
           "WHERE [ProLineCode] = '{0}'";
        private readonly static string DELETE_TEAM_VARIABLE = "DELETE FROM [pret].[dbo].[TeamVariable] " +
           "WHERE [ProLineCode] = '{0}'";
        private readonly static string DELETE_WAITINGORDER_VARIABLE = "DELETE FROM [pret].[dbo].[WaitingOrderVariable] " +
           "WHERE [ProLineCode] = '{0}'";
        #endregion

        private readonly static int DaySeconds = 5 * 24 * 3600;
        private readonly static DateTime StartDay = DateTime.Parse("2014/12/10 20:00").ToUniversalTime();

        private Dictionary<string, List<string>> devicePrefixDic = new Dictionary<string, List<string>>();

        public bool IsConnected
        {
            get 
            {
                if (conn.State == System.Data.ConnectionState.Closed || conn.State == System.Data.ConnectionState.Broken)
                    return false;
                else
                    return true;
            }
        }

        private System.Diagnostics.EventLog log;
        private OleDbConnection conn = new OleDbConnection();

        public WinCCDataProcess(string serverAddress, string dbName, string userid, string password, EventLog log)
        {
            this.log = log;
            InitializeDeviceList();
            ConnectWinCC(serverAddress, dbName, userid, password);
            //this.TestConnectWinCC();
        }

        public void Dispose()
        {
            try
            {
                if (conn != null && conn.State != System.Data.ConnectionState.Closed)
                {
                    conn.Close();
                }
            }
            catch(Exception ex)
            {
                string msg = "WinCCDataProcess.Dispose() Failed: " + ex.Message;
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
            }
        }

        private void ConnectWinCC(string servername, string dbName, string userid, string password)
        {
            if (IsConnected == false)
            {
                try
                {
                    conn.ConnectionString = string.Format("Provider=WinCCOLEDBProvider.1;Data Source={0};Catalog={1};User ID={2};Password={3};", servername, dbName, userid, password);
                    conn.Open();
                }
                catch (Exception ex)
                {
                    string msg = "WinCCDataProcess.ConnectWinCC() Failed: " + ex.Message;
                    log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                }
            }
        }

        public void TestConnectWinCC()
        {
            OleDbCommand command = null;
            OleDbDataReader reader = null;
            try
            {
                string query = "TAG:R,1,'2014-09-01 00:00:00.000','0000-00-00 00:00:00.000', 'TIMESTEP=5,258'";
                using(command = new OleDbCommand(query, this.conn))
                {
                    reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        DateTime time = reader.GetDateTime(1);
                        string value = reader["RealValue"].ToString();
                    }
                    reader.Close();
                }
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                if (command != null)
                    command.Dispose();
                string msg = "WinCCDataProcess.TestConnectWinCC() Failed: " + ex.Message;
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
            }
        }

        /// <summary>
        /// 从config文件中提取WINCC里面设备变量的前缀
        /// </summary>
        private void InitializeDeviceList()
        {
            this.devicePrefixDic = new Dictionary<string, List<string>>();
            foreach (string key in ConfigurationManager.AppSettings.Keys)
            {
                List<string> list = new List<string>();
                int count = Int32.Parse(ConfigurationManager.AppSettings[key]);
                string var = key.Substring(0, 2);
                for (int i = 1; i <= count; i++)
                {
                    list.Add(var + i.ToString());
                }
                if (list.Count > 0)
                    this.devicePrefixDic.Add(key, list);
            }
        }

        //#region 挤出机
        ///// <summary>
        ///// 获取所有挤出机从开始时间到现在时间之间的所有生产数据
        ///// </summary>
        ///// <param name="startTime">存储的是每个生产线和它上面最近的记录时间，如: {"JC1", "2014-11-24"}</param>
        ///// <returns></returns>
        //public List<JCJData> GetJCJData(Dictionary<string, DateTime> startTime)
        //{
        //    List<JCJData> retList = new List<JCJData>();
        //    // 如果没有挤出机前缀列表，则返回null
        //    if (!this.devicePrefixDic.ContainsKey(JCJName))
        //        return retList;

        //    //log.WriteEntry("开始收集挤出机数据:");
        //    foreach (string prefix in this.devicePrefixDic[JCJName])
        //    {
        //        DateTime latest = StartDay;
        //        if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
        //            latest = startTime[prefix].ToUniversalTime();

        //        string msg = string.Format("从{0}开始收集挤出机{1}数据。", latest, prefix);
        //        //log.WriteEntry(msg);
        //        // 如果当前WINCC含有的数据量超过5天，我们通过多次遍历，每次遍历间隔为1天的数据来记录挤出机的数值
        //        DateTime nowTime = DateTime.UtcNow;
        //        DateTime tmpTime = latest;
        //        DateTime stopTime = GetStopTime(tmpTime, nowTime);
        //        //msg = string.Format("开始收集挤出机{0}数据", prefix);
        //        //log.WriteEntry(msg);
        //        do
        //        {
        //            msg = string.Format("开始收集挤出机{2}数据，时间{0} - {1}", latest, stopTime, prefix);
        //            log.WriteEntry(msg);
        //            //GetJCJData2(prefix, latest, stopTime);
        //            List<JCJData> list = GetJCJData(prefix, latest, stopTime);
        //            if (list != null && list.Count > 0)
        //            {
        //                //msg = string.Format("挤出机{0}取到数据数{1}", prefix, list.Count);
        //                //log.WriteEntry(msg);
        //                retList.AddRange(list);
        //            }
        //            // 将上次记录的时间加1秒
        //            latest = stopTime.AddSeconds(1);
        //            tmpTime = latest;
        //            stopTime = GetStopTime(tmpTime, nowTime);
        //        } while (stopTime <= nowTime && latest < stopTime);
        //    }
        //    return retList;
        //}

        ///// <summary>
        ///// 获取指定挤出机生产线的生产数据
        ///// </summary>
        ///// <param name="prefix"></param>
        ///// <param name="startTime"></param>
        ///// <returns></returns>
        //private List<JCJData> GetJCJData(string prefix, DateTime startTime, DateTime stopTime)
        //{
        //    try
        //    {
        //        // 获得所有变量的变量名
        //        string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
        //        string strVar = "";
        //        foreach (string var in JCVariableList)
        //        {
        //            strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
        //        }
        //        string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
        //        log.WriteEntry(string.Format("挤出机{0} 时间段 {1} - {2}.", varTeam, startTime, stopTime));
        //        int minCount = int.MaxValue;
        //        Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, JCVariableList, ref minCount);
        //        if (varDic == null || varDic.Count == 0)
        //        {
        //            string msg = string.Format("挤出机{0}的记录为空。", prefix);
        //            log.WriteEntry(msg);
        //            return null;
        //        }
        //        if (varDic.Count != JCVariableList.Length + 1)
        //        {
        //            string msg = string.Format("挤出机{4}获取的变量数'{0}'和变量列表数'{1}'不匹配!\r\n时间段:{2}--{3}, 最小变量总数{5}", varDic.Count, JCVariableList.Length, startTime, stopTime, varTeam, minCount);
        //            string var = "";
        //            foreach (KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                var += string.Format("{0}\r\n", item.Key);
        //            }
        //            var += "\r\n";
        //            foreach (string item in JCVariableList)
        //            {
        //                var += string.Format("{0}\r\n", item);
        //            }
        //            log.WriteEntry(msg + "\r\n" + var, EventLogEntryType.Error);
        //            return null;
        //        }

        //        // 记录挤出机数据
        //        List<JCJData> retList = new List<JCJData>();
        //        Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
        //        if (varDic["JsProduce"][0] == "1")
        //        {
        //            foreach (KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                newDic.Add(item.Key, new List<string>());
        //                newDic[item.Key].Add(item.Value[0]);
        //            }
        //        }
        //        // 如果第一个JsProduce的值为0，那么这个标志位有可能记录的是上次刚刚完结的时间
        //        // 所以我们在这里单独记录这个数据到一个新的JCJData 对象中
        //        else
        //        {
        //            Dictionary<string, string> tmpDic = new Dictionary<string, string>();
        //            foreach (KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                tmpDic.Add(item.Key, item.Value[0]);
        //            }
        //            JCJData objData = JCJData.ConvertDictionary2JCJData(tmpDic);
        //            retList.Add(objData);
        //            //string msg = string.Format("挤出机{0}取到生产线{1}和开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
        //            //log.WriteEntry(msg);
        //        }

        //        bool isTrue = false;
        //        for (int i = 1; i < minCount; i++)
        //        {
        //            if (varDic["JsProduce"][i] == "1")
        //            {
        //                isTrue = true;
        //                foreach (KeyValuePair<string, List<string>> item in varDic)
        //                {
        //                    if (!newDic.ContainsKey(item.Key))
        //                        newDic.Add(item.Key, new List<string>());
        //                    newDic[item.Key].Add(item.Value[i]);
        //                }
        //            }
        //            else
        //            {
        //                // 如果前一个标志是1，当前的标志是0，说明一个包装结束, 记录包装信息和更新记录时间
        //                if (varDic["JsProduce"][i - 1] == "1")
        //                {
        //                    JCJData objData = JCJData.ConvertDictionary2JCJData(newDic, prefix);
        //                    objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
        //                    retList.Add(objData);
        //                    objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
        //                    string msg = string.Format("挤出机{0}取到生产线{1}和开始时间{2}，结束时间{3}", prefix, objData.ProductionLine, objData.StartTime, objData.EndTime);
        //                    log.WriteEntry(msg);
        //                    newDic.Clear();
        //                }
        //            }
        //        }
        //        // 有可能当前的时间间隔里的运行标志“JsProduce”都是1， 那就需要把newDic里的内容存入到对象中
        //        if (newDic.Count > 1)
        //        {
        //            JCJData objData = JCJData.ConvertDictionary2JCJData(newDic, prefix);
        //            retList.Add(objData);
        //        }
        //        if (isTrue)
        //            log.WriteEntry("JsProduce 为 1");
        //        else
        //            log.WriteEntry(string.Format("JsProduce 都为 0, 数据数量{0}", retList.Count));

        //        return retList;
        //    }
        //    catch (OleDbException ex)
        //    {
        //        string msg = string.Format("WinCCDataProcess.GetJCJData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
        //        log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
        //        return null;
        //    }
        //}

        //private void TestGetJCJData2(string prefix, string[] VarList, DateTime startTime, DateTime stopTime)
        //{
        //    OleDbCommand command = null;
        //    OleDbDataReader reader = null;
        //    try
        //    {
        //        int maxcount = 0;
        //        int mincount = int.MaxValue;
        //        string maxName = "";
        //        string minName = "";
        //        foreach (string var in VarList)
        //        {
        //            int count = 0;

        //            bool hasValue = false;
        //            string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
        //            string strVar = string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
        //            string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, "2014-12-10", stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
        //            using (command = new OleDbCommand(query, this.conn))
        //            {
        //                reader = command.ExecuteReader();
        //                while (reader.Read())
        //                {
        //                    count++;
        //                    hasValue = true;
        //                }
        //                reader.Close();
        //                if (maxcount < count)
        //                {
        //                    maxName = var;
        //                    maxcount = count;
        //                }
        //                if (mincount > count)
        //                {
        //                    minName = var;
        //                    mincount = count;
        //                }
        //            }
        //            if (!hasValue)
        //            {
        //                string error = string.Format("The variable {0} not found in {1} - {2}", var, startTime, stopTime);
        //                log.WriteEntry(error, System.Diagnostics.EventLogEntryType.Error);
        //            }
        //        }
        //        int reult = 0;
        //        return;
        //    }
        //    catch (Exception ex)
        //    {
        //        if (reader != null && !reader.IsClosed)
        //            reader.Close();
        //        if (command != null)
        //            command.Dispose();
        //        string msg = string.Format("WinCCDataProcess.TestGetJCJData2() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
        //        log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
        //    }
        //}
        //#endregion

        #region 挤出机
        /// <summary>
        /// 获取所有挤出机从开始时间到现在时间之间的所有生产数据
        /// </summary>
        /// <param name="startTime">存储的是每个生产线和它上面最近的记录时间，如: {"JC1", "2014-11-24"}</param>
        /// <returns></returns>
        public List<JCJData> GetJCJSummaryData(Dictionary<string, DateTime> startTime)
        {
            try
            {
                List<JCJData> retList = new List<JCJData>();
                // 如果没有挤出机前缀列表，则返回null
                if (!this.devicePrefixDic.ContainsKey(JCJName))
                    return retList;

                //log.WriteEntry("开始收集挤出机数据:");
                foreach (string prefix in this.devicePrefixDic[JCJName])
                {
                    DateTime latest = StartDay;
                    if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
                        latest = startTime[prefix].ToUniversalTime();

                    string msg = string.Format("从{0}开始收集挤出机summary{1}数据。", latest, prefix);
                    //log.WriteEntry(msg);
                    // 如果当前WINCC含有的数据量超过5天，我们通过多次遍历，每次遍历间隔为5天的数据来记录挤出机的数值
                    DateTime nowTime = DateTime.UtcNow;
                    DateTime tmpTime = latest;
                    DateTime stopTime = GetStopTime(tmpTime, nowTime);
                    //msg = string.Format("开始收集挤出机{0}数据", prefix);
                    //log.WriteEntry(msg);
                    do
                    {
                        msg = string.Format("开始收集挤出机summary{2}数据，时间{0} - {1}", latest, stopTime, prefix);
                        //log.WriteEntry(msg);
                        //TestGetJCJData2(prefix, JCSummaryVariableList, latest, stopTime);
                        List<JCJData> list = GetJCJSummaryData(prefix, latest, stopTime);
                        if (list != null && list.Count > 0)
                        {
                            //msg = string.Format("挤出机Summary{0}取到数据数{1}", prefix, list.Count);
                            //log.WriteEntry(msg);
                            retList.AddRange(list);
                        }
                        // 将上次记录的时间加1秒
                        latest = stopTime.AddSeconds(1);
                        tmpTime = latest;
                        stopTime = GetStopTime(tmpTime, nowTime);
                    } while (latest < stopTime);
                }
                return retList;
            }
            catch (Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.GetJCJSummaryData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        /// <summary>
        /// 获取指定挤出机生产线的summary生产数据
        /// </summary>
        /// <param name="prefix"></param>
        /// <param name="startTime"></param>
        /// <returns></returns>
        private List<JCJData> GetJCJSummaryData(string prefix, DateTime startTime, DateTime stopTime)
        {
            try
            {
                // 获得所有变量的变量名
                string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
                //string strVar = "";
                //foreach (string var in JCSummaryVariableList)
                //{
                //    strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                //}
                //string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                //log.WriteEntry(string.Format("挤出机Summary{0} 时间段 {1} - {2}.", varTeam, startTime, stopTime));
                int minCount = int.MaxValue;
                //Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, JCSummaryVariableList, ref minCount);
                Dictionary<string, List<string>> varDic = GetWINCCVariableList2(VariableType.JCJSummaryType, varTeam, prefix, JCSummaryVariableList, startTime, stopTime, ref minCount);
                if (varDic == null || varDic.Count == 0)
                {
                    string msg = string.Format("挤出机Summary{0}的记录为空。", prefix);
                    //log.WriteEntry(msg);
                    return null;
                }
                if (varDic.Count != JCSummaryVariableList.Length + 1)
                {
                    string msg = string.Format("挤出机Summary{4}获取的变量数'{0}'和变量列表数'{1}'不匹配!\r\n时间段:{2}--{3}, 最小变量总数{5}", varDic.Count, JCSummaryVariableList.Length, startTime, stopTime, varTeam, minCount);
                    log.WriteEntry(msg, EventLogEntryType.Error);
                    return null;
                }

                // 记录挤出机Summary数据
                List<JCJData> retList = new List<JCJData>();
                Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
                if (varDic["JsProduce"][0] == "1")
                {
                    foreach (KeyValuePair<string, List<string>> item in varDic)
                    {
                        newDic.Add(item.Key, new List<string>());
                        newDic[item.Key].Add(item.Value[0]);
                    }
                }
                // 如果第一个JsProduce的值为0，那么这个标志位有可能记录的是上次刚刚完结的时间
                // 所以我们在这里单独记录这个数据到一个新的JCJData 对象中
                else
                {
                    Dictionary<string, string> tmpDic = new Dictionary<string, string>();
                    foreach (KeyValuePair<string, List<string>> item in varDic)
                    {
                        tmpDic.Add(item.Key, item.Value[0]);
                    }
                    JCJData objData = JCJData.ConvertDictionary2JCJData(tmpDic, prefix);
                    retList.Add(objData);
                    //string msg = string.Format("挤出机{0}取到生产线{1}和开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
                    //log.WriteEntry(msg);
                }

                //bool isTrue = false;
                for (int i = 1; i < minCount; i++)
                {
                    if (varDic["JsProduce"][i] == "1")
                    {
                        //isTrue = true;
                        foreach (KeyValuePair<string, List<string>> item in varDic)
                        {
                            if (!newDic.ContainsKey(item.Key))
                                newDic.Add(item.Key, new List<string>());
                            newDic[item.Key].Add(item.Value[i]);
                        }
                    }
                    else
                    {
                        // 如果前一个标志是1，当前的标志是0，说明一个包装结束, 记录包装信息和更新记录时间
                        if (varDic["JsProduce"][i - 1] == "1")
                        {
                            JCJData objData = JCJData.ConvertDictionary2JCJData2(newDic, prefix);
                            objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
                            retList.Add(objData);
                            objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
                            string msg = string.Format("挤出机{0}取到生产线{1}和开始时间{2}，结束时间{3}", prefix, objData.ProductionLine, objData.StartTime, objData.EndTime);
                            //log.WriteEntry(msg);
                            newDic.Clear();
                        }
                    }
                }
                // 有可能当前的时间间隔里的运行标志“JsProduce”都是1， 那就需要把newDic里的内容存入到对象中
                if (newDic.Count > 1)
                {
                    JCJData objData = JCJData.ConvertDictionary2JCJData2(newDic, prefix);
                    retList.Add(objData);
                }
                //if (isTrue)
                //    log.WriteEntry("JsProduce 为 1");
                //else
                //    log.WriteEntry(string.Format("JsProduce 都为 0, 数据数量{0}", retList.Count));

                return retList;
            }
            catch (OleDbException ex)
            {
                string msg = string.Format("WinCCDataProcess.GetJCJData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }

        public Dictionary<string, List<JCJDetail>> GetJCJDetailData(Dictionary<string, DateTime> startTime)
        {
            try
            {
                Dictionary<string, List<JCJDetail>> retDic = new Dictionary<string, List<JCJDetail>>();
                // 如果没有挤出机前缀列表，则返回null
                if (!this.devicePrefixDic.ContainsKey(JCJName))
                    return retDic;

                //log.WriteEntry("开始收集挤出机数据:");
                foreach (string prefix in this.devicePrefixDic[JCJName])
                {
                    DateTime latest = StartDay;
                    if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
                        latest = startTime[prefix].ToUniversalTime();

                    string msg = string.Format("从{0}开始收集挤出机Detail{1}数据。", latest, prefix);
                    //log.WriteEntry(msg);
                    // 如果当前WINCC含有的数据量超过5天，我们通过多次遍历，每次遍历间隔为5天的数据来记录挤出机的数值
                    DateTime nowTime = DateTime.UtcNow;
                    DateTime tmpTime = latest;
                    DateTime stopTime = GetStopTime(tmpTime, nowTime);
                    //msg = string.Format("开始收集挤出机{0}数据", prefix);
                    //log.WriteEntry(msg);
                    do
                    {
                        msg = string.Format("开始收集挤出机Detail{2}数据，时间{0} - {1}", latest, stopTime, prefix);
                        //log.WriteEntry(msg);
                        //TestGetJCJData2(prefix, JCDetailVariableList, latest, stopTime);
                        Dictionary<string, List<JCJDetail>> dic = GetJCJDetailData(prefix, latest, stopTime);
                        if (dic != null)
                        {
                            //msg = string.Format("挤出机Detail{0}取到数据数{1}", prefix, list.Count);
                            //log.WriteEntry(msg);
                            foreach(KeyValuePair<string, List<JCJDetail>> item in dic)
                            {
                                // 将订单号相同的信息放在一个字典中
                                if (retDic.Keys.Contains(item.Key))
                                    retDic[item.Key].AddRange(item.Value);
                                else
                                    retDic.Add(item.Key, item.Value);
                            }
                        }
                        // 将上次记录的时间加1秒
                        latest = stopTime.AddSeconds(1);
                        tmpTime = latest;
                        stopTime = GetStopTime(tmpTime, nowTime);
                    } while (stopTime <= nowTime && latest < stopTime);
                }
                return retDic;
            }
            catch (Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.GetJCJDetailData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }            
        }
        /// <summary>
        /// 获取指定挤出机生产线的summary生产数据
        /// </summary>
        /// <param name="prefix"></param>
        /// <param name="startTime"></param>
        /// <returns></returns>
        private Dictionary<string, List<JCJDetail>> GetJCJDetailData(string prefix, DateTime startTime, DateTime stopTime)
        {
            try
            {
                // 获得所有变量的变量名
                string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
                //string strVar = "";
                //foreach (string var in JCDetailVariableList)
                //{
                //    strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                //}
                //string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                //log.WriteEntry(string.Format("挤出机Detail{0} 时间段 {1} - {2}.", varTeam, startTime, stopTime));
                int minCount = int.MaxValue;
                //Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, JCDetailVariableList, ref minCount);
                Dictionary<string, List<string>> varDic = GetWINCCVariableList2(VariableType.JCJDetailType, varTeam, prefix, JCDetailVariableList, startTime, stopTime, ref minCount);
                if (varDic == null || varDic.Count == 0)
                {
                    string msg = string.Format("挤出机Detail{0}的记录为空。", prefix);
                    //log.WriteEntry(msg);
                    return null;
                }
                if (varDic.Count != JCDetailVariableList.Length + 1)
                {
                    string msg = string.Format("挤出机Detail{4}获取的变量数'{0}'和变量列表数'{1}'不匹配!\r\n时间段:{2}--{3}, 最小变量总数{5}", varDic.Count, JCSummaryVariableList.Length, startTime, stopTime, varTeam, minCount);
                    log.WriteEntry(msg, EventLogEntryType.Error);
                    return null;
                }

                Dictionary<string, List<JCJDetail>> retDic = new Dictionary<string, List<JCJDetail>>();
                Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
                for (int i = 0; i < minCount; i++)
                {
                    if (varDic["JsProduce"][i] == "1")
                    {
                        foreach (KeyValuePair<string, List<string>> item in varDic)
                        {
                            if (!newDic.ContainsKey(item.Key))
                                newDic.Add(item.Key, new List<string>());
                            newDic[item.Key].Add(item.Value[i]);
                        }
                    }
                    else
                    {
                        // 如果前一个标志是1，当前的标志是0，说明一个包装结束, 记录包装信息和更新记录时间
                        if (i > 0 && varDic["JsProduce"][i - 1] == "1")
                        {
                            Dictionary<string, List<JCJDetail>> dic = JCJDetail.Convert2JCJDetail(newDic, prefix);
                            foreach(KeyValuePair<string, List<JCJDetail>> item in dic)
                            {
                                if (retDic.Keys.Contains(item.Key))
                                    retDic[item.Key].AddRange(item.Value);
                                else
                                    retDic.Add(item.Key, item.Value);
                            }
                            newDic.Clear();
                        }
                    }
                }
                // 有可能当前的时间间隔里的运行标志“JsProduce”都是1， 那就需要把newDic里的内容存入到对象中
                if (newDic.Count > 1)
                {
                    Dictionary<string, List<JCJDetail>> dic = JCJDetail.Convert2JCJDetail(newDic, prefix);
                    foreach (KeyValuePair<string, List<JCJDetail>> item in dic)
                    {
                        if (retDic.Keys.Contains(item.Key))
                            retDic[item.Key].AddRange(item.Value);
                        else
                            retDic.Add(item.Key, item.Value);
                    }
                }
                //if (isTrue)
                //    log.WriteEntry("JsProduce 为 1");
                //else
                //    log.WriteEntry(string.Format("JsProduce 都为 0, 数据数量{0}", retDic.Count));

                return retDic;
            }
            catch (OleDbException ex)
            {
                string msg = string.Format("WinCCDataProcess.GetJCJDetailData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        #endregion

        //#region 均化机
        //public List<JHJData> GetJHJData(Dictionary<string, DateTime> startTime)
        //{
        //    List<JHJData> retList = new List<JHJData>();
        //    // 如果没有均化机前缀列表，则返回null
        //    if (!this.devicePrefixDic.ContainsKey(JHJName))
        //        return retList;
        //    foreach (string prefix in this.devicePrefixDic[JHJName])
        //    {
        //        DateTime latest = StartDay;
        //        if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
        //            latest = startTime[prefix].ToUniversalTime();

        //        // 如果当前WINCC含有的数据量超过1天，我们通过多次遍历，每次遍历间隔为1天的数据来记录均化机的数值
        //        DateTime nowTime = DateTime.UtcNow;
        //        DateTime tmpTime = latest;
        //        DateTime stopTime = GetStopTime(tmpTime, nowTime);
        //        string msg = string.Format("开始收集均化机{0}数据", prefix);
        //        log.WriteEntry(msg);
        //        do
        //        {
        //            //string msg = string.Format("开始收集均化机{2}数据，时间{0} - {1}", latest, stopTime, prefix);
        //            //log.WriteEntry(msg);
        //            List<JHJData> list = GetJHJData(prefix, latest, stopTime);
        //            if (list != null && list.Count > 0)
        //            {
        //                //msg = string.Format("挤出机{0}取到数据数{1}", prefix, list.Count);
        //                //log.WriteEntry(msg);
        //                retList.AddRange(list);
        //            }
        //            // 将上次记录的时间加1秒
        //            latest = stopTime.AddSeconds(1);
        //            tmpTime = latest;
        //            stopTime = GetStopTime(tmpTime, nowTime);
        //        } while (stopTime <= nowTime && latest < stopTime);
        //    }
        //    return retList;
        //}

        //private List<JHJData> GetJHJData(string prefix, DateTime startTime, DateTime stopTime)
        //{
        //    try
        //    {
        //        // 获得所有变量的变量名
        //        string varTeam = string.Format("{0}{1}", JHJName, prefix.Substring(2));
        //        string strVar = "";
        //        foreach (string var in JHVariableList)
        //        {
        //            strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
        //        }
        //        string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
        //        log.WriteEntry(string.Format("均化机{0} 时间段 {1} - {2}.", varTeam, startTime, stopTime));
        //        int minCount = int.MaxValue;
        //        Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, JHVariableList, ref minCount);
        //        if (varDic == null || varDic.Count == 0)
        //        {
        //            string msg = string.Format("均化机{0}的记录为空。", prefix);
        //            log.WriteEntry(msg);
        //            return null;
        //        }
        //        if (varDic.Count != JHVariableList.Length + 1)
        //        {
        //            string msg = string.Format("均化机{2}获取的变量数'{0}'和变量列表数'{1}'不匹配! 最小变量总数{3}", varDic.Count, JHVariableList.Length, varTeam, minCount);
        //            string var = "";
        //            foreach(KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                var += string.Format("{0}\r\n", item.Key);
        //            }
        //            var += "\r\n";
        //            foreach(string item in JHVariableList)
        //            {
        //                var += string.Format("{0}\r\n", item);
        //            }
        //            log.WriteEntry(msg + "\r\n" + var, EventLogEntryType.Error);
        //            return null;
        //        }

        //        // 记录均化机数据
        //        List<JHJData> retList = new List<JHJData>();
        //        Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
        //        if (varDic["PJobSP"][0] == "1")
        //        {
        //            foreach (KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                newDic.Add(item.Key, new List<string>());
        //                newDic[item.Key].Add(item.Value[0]);
        //            }
        //        }
        //        // 如果第一个PJobSP的值为0，那么这个标志位有可能记录的是上次刚刚完结的包装时间
        //        // 所以我们在这里单独记录这个数据到一个新的JHJData 对象中
        //        else
        //        {
        //            Dictionary<string, string> tmpDic = new Dictionary<string, string>();
        //            foreach (KeyValuePair<string, List<string>> item in varDic)
        //            {
        //                tmpDic.Add(item.Key, item.Value[0]);
        //            }
        //            JHJData objData = JHJData.ConvertDictionary2JHJData(tmpDic, prefix);
        //            retList.Add(objData);
        //            string msg = string.Format("均化机{0}取到生产线{1}和开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
        //            log.WriteEntry(msg);
        //        }

        //        for (int i = 1; i < minCount; i++)
        //        {
        //            if (varDic["PJobSP"][i] == "1")
        //            {
        //                foreach (KeyValuePair<string, List<string>> item in varDic)
        //                {
        //                    if (!newDic.ContainsKey(item.Key))
        //                        newDic.Add(item.Key, new List<string>());
        //                    newDic[item.Key].Add(item.Value[i]);
        //                }
        //            }
        //            else
        //            {
        //                // 如果前一个标志是1，当前的标志是0，说明一个包装结束, 记录包装信息和更新记录时间
        //                if (varDic["PJobSP"][i - 1] == "1")
        //                {
        //                    JHJData objData = JHJData.ConvertDictionary2JHJData(newDic, prefix);
        //                    objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
        //                    string msg = string.Format("均化机{0}取到生产线{1}和开始时间{2}，结束时间{3}", prefix, objData.ProductionLine, objData.StartTime, objData.EndTime);
        //                    log.WriteEntry(msg);
        //                    retList.Add(objData);
        //                    newDic.Clear();
        //                }
        //            }
        //        }

        //        // 有可能当前的时间间隔里的运行标志“PJobSP”都是1， 那就需要把newDic里的内容存入到对象中
        //        if (newDic.Count > 1)
        //        {
        //            JHJData objData = JHJData.ConvertDictionary2JHJData(newDic, prefix);
        //            string msg = string.Format("均化机{0}取到生产线{1}与开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
        //            log.WriteEntry(msg);
        //            retList.Add(objData);
        //        }
        //        return retList;
        //    }
        //    catch (Exception ex)
        //    {
        //        string msg = string.Format("WinCCDataProcess.GetJHJData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
        //        log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
        //        return null;
        //    }
        //}
        //#endregion

        #region 均化机
        public List<JHJData> GetJHJData(Dictionary<string, DateTime> startTime)
        {
            List<JHJData> retList = new List<JHJData>();
            // 如果没有均化机前缀列表，则返回null
            if (!this.devicePrefixDic.ContainsKey(JHJName))
                return retList;
            foreach (string prefix in this.devicePrefixDic[JHJName])
            {
                DateTime latest = StartDay;
                if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
                    latest = startTime[prefix].ToUniversalTime();

                // 如果当前WINCC含有的数据量超过1天，我们通过多次遍历，每次遍历间隔为1天的数据来记录均化机的数值
                DateTime nowTime = DateTime.UtcNow;
                DateTime tmpTime = latest;
                DateTime stopTime = GetStopTime(tmpTime, nowTime);
                string msg = string.Format("开始收集均化机{0}数据", prefix);
                //log.WriteEntry(msg);
                do
                {
                    //string msg = string.Format("开始收集均化机{2}数据，时间{0} - {1}", latest, stopTime, prefix);
                    //log.WriteEntry(msg);
                    List<JHJData> list = GetJHJData(prefix, latest, stopTime);
                    if (list != null && list.Count > 0)
                    {
                        //msg = string.Format("挤出机{0}取到数据数{1}", prefix, list.Count);
                        //log.WriteEntry(msg);
                        retList.AddRange(list);
                    }
                    // 将上次记录的时间加1秒
                    latest = stopTime.AddSeconds(1);
                    tmpTime = latest;
                    stopTime = GetStopTime(tmpTime, nowTime);
                } while (stopTime <= nowTime && latest < stopTime);
            }
            return retList;
        }

        private List<JHJData> GetJHJData(string prefix, DateTime startTime, DateTime stopTime)
        {
            try
            {
                // 获得所有变量的变量名
                string varTeam = string.Format("{0}{1}", JHJName, prefix.Substring(2));
                //string strVar = "";
                //foreach (string var in JHVariableList)
                //{
                //    strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                //}
                //string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                //log.WriteEntry(string.Format("均化机{0} 时间段 {1} - {2}.", varTeam, startTime, stopTime));
                int minCount = int.MaxValue;
                //Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, JHVariableList, ref minCount);
                Dictionary<string, List<string>> varDic = GetWINCCVariableList2(VariableType.JHJDataType, varTeam, prefix, JHVariableList, startTime, stopTime, ref minCount);
                if (varDic == null || varDic.Count == 0)
                {
                    string msg = string.Format("均化机{0}的记录为空。", prefix);
                    //log.WriteEntry(msg);
                    return null;
                }
                if (varDic.Count != JHVariableList.Length + 1)
                {
                    string msg = string.Format("均化机{2}获取的变量数'{0}'和变量列表数'{1}'不匹配! 最小变量总数{3}", varDic.Count, JHVariableList.Length, varTeam, minCount);
                    log.WriteEntry(msg, EventLogEntryType.Error);
                    return null;
                }

                // 记录均化机数据
                List<JHJData> retList = new List<JHJData>();
                Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
                if (varDic["PJobSP"][0] == "1")
                {
                    foreach (KeyValuePair<string, List<string>> item in varDic)
                    {
                        newDic.Add(item.Key, new List<string>());
                        newDic[item.Key].Add(item.Value[0]);
                    }
                }
                // 如果第一个PJobSP的值为0，那么这个标志位有可能记录的是上次刚刚完结的包装时间
                // 所以我们在这里单独记录这个数据到一个新的JHJData 对象中
                else
                {
                    Dictionary<string, string> tmpDic = new Dictionary<string, string>();
                    foreach (KeyValuePair<string, List<string>> item in varDic)
                    {
                        tmpDic.Add(item.Key, item.Value[0]);
                    }
                    JHJData objData = JHJData.ConvertDictionary2JHJData(tmpDic, prefix);
                    retList.Add(objData);
                    string msg = string.Format("均化机{0}取到生产线{1}和开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
                    //log.WriteEntry(msg);
                }

                for (int i = 1; i < minCount; i++)
                {
                    if (varDic["PJobSP"][i] == "1")
                    {
                        foreach (KeyValuePair<string, List<string>> item in varDic)
                        {
                            if (!newDic.ContainsKey(item.Key))
                                newDic.Add(item.Key, new List<string>());
                            newDic[item.Key].Add(item.Value[i]);
                        }
                    }
                    else
                    {
                        // 如果前一个标志是1，当前的标志是0，说明一个包装结束, 记录包装信息和更新记录时间
                        if (varDic["PJobSP"][i - 1] == "1")
                        {
                            JHJData objData = JHJData.ConvertDictionary2JHJData(newDic, prefix);
                            objData.EndTime = DateTime.Parse(varDic["Time"][i - 1]);
                            string msg = string.Format("均化机{0}取到生产线{1}和开始时间{2}，结束时间{3}", prefix, objData.ProductionLine, objData.StartTime, objData.EndTime);
                            //log.WriteEntry(msg);
                            retList.Add(objData);
                            newDic.Clear();
                        }
                    }
                }

                // 有可能当前的时间间隔里的运行标志“PJobSP”都是1， 那就需要把newDic里的内容存入到对象中
                if (newDic.Count > 1)
                {
                    JHJData objData = JHJData.ConvertDictionary2JHJData(newDic, prefix);
                    string msg = string.Format("均化机{0}取到生产线{1}与开始时间{2}", prefix, objData.ProductionLine, objData.StartTime);
                    //log.WriteEntry(msg);
                    retList.Add(objData);
                }
                return retList;
            }
            catch (Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.GetJHJData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        #endregion

        #region 电表
        public List<MeterData> GetMeterData(DateTime startTime)
        {
            List<MeterData> retList = new List<MeterData>();
            foreach(KeyValuePair<string, List<string>> item in this.devicePrefixDic)
            {
                foreach(string prefix in item.Value)
                {
                    List<MeterData> tmp = GetMeterData(prefix, startTime);
                    if (tmp != null && tmp.Count > 0)
                        retList.AddRange(tmp);
                }
            }
            return retList;
        }
        private List<MeterData> GetMeterData(string prefix, DateTime startTime)
        {
            try
            {
                // 获得所有变量的变量名
                string strVar = "";
                foreach (string var in MeterVariableList)
                {
                    strVar += string.Format("'{0}\\{1}_{2}';", prefix, prefix, var);
                }
                string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), "0000-00-00 00:00:00:000");
                int minCount = int.MaxValue;
                Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, MeterVariableList, ref minCount);
                if (varDic == null || varDic.Count == 0)
                    return null;

                // 记录电表数据
                List<MeterData> retList = new List<MeterData>();
                Dictionary<string, List<string>> newDic = new Dictionary<string, List<string>>();
                for (int i = 0; i < varDic["Time"].Count; i++)
                {
                    // 由于WINCC的数据记录是按秒记录的，所以这里取60秒内的数据并将其合并为一个MeterData对象
                    if (i != 0 && i % 60 == 0)
                    {
                        MeterData obj = MeterData.ConvertDictionary2MeterData(newDic);
                        retList.Add(obj);
                        newDic.Clear();
                    }
                    else
                    {
                        foreach (KeyValuePair<string, List<string>> item in varDic)
                        {
                            if (!newDic.ContainsKey(item.Key))
                                newDic.Add(item.Key, new List<string>());
                            newDic[item.Key].Add(item.Value[i]);
                        }
                    }                        
                }
                if (newDic.Count > 1)
                {
                    MeterData obj = MeterData.ConvertDictionary2MeterData(newDic);
                    retList.Add(obj);
                }
                return retList;
            }
            catch(Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.GetMeterData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        #endregion

        #region 待产信息
        public List<WaitingOrder> GetWaitingOrderList()
        {
            List<WaitingOrder> retList = new List<WaitingOrder>();
            if (!this.devicePrefixDic.ContainsKey(JCJName))
                return retList;

            foreach (string prefix in this.devicePrefixDic[JCJName])
            {
                WaitingOrder order = GetWaitingOrder(prefix);
                if(order != null)
                    retList.Add(order);
            }
            return retList;
        }
        private WaitingOrder GetWaitingOrder(string prefix)
        {
            try
            {
                // 获得所有变量的变量名
                string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
                //string strVar = "";
                //foreach (string var in WaitingVarList)
                //{
                //    strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                //}
                //// 获得最近时间段内的待产信息
                //string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, "0000-00-00 00:00:30:000", "0000-00-00 00:00:00:000");
                int minCount = int.MaxValue;
                //Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, WaitingVarList, ref minCount);
                Dictionary<string, List<string>> varDic = GetWINCCVariableList2(VariableType.WaitingOrderType, varTeam, prefix, WaitingVarList, DateTime.UtcNow.AddSeconds(-30), DateTime.UtcNow, ref minCount);
                if (varDic == null || varDic.Count == 0)
                    return null;

                WaitingOrder order = WaitingOrder.ConvertDictionary2WaitingOrder(varDic, minCount);
                return order;
            }
            catch (Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.GetWaitingOrder() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        #endregion

        #region 班组工作时间
        public List<TeamWorkTime> GetTeamWorkTimeData(Dictionary<string, DateTime> startTime)
        {
            List<TeamWorkTime> retList = new List<TeamWorkTime>();
            // 如果没有挤出机前缀列表，则返回null
            if (!this.devicePrefixDic.ContainsKey(JCJName))
                return retList;
            // 从每个挤出机生产线上拿团队名单
            foreach (string prefix in this.devicePrefixDic[JCJName])
            {
                DateTime latest = StartDay;
                if (startTime != null && startTime.Count > 0 && startTime.ContainsKey(prefix))
                    latest = startTime[prefix].ToUniversalTime();
                List<TeamWorkTime> list = GetTeamWorkTimeData(prefix, latest);
                if (list != null && list.Count > 0)
                    retList.AddRange(list);
            }
            return retList;
        }
        private List<TeamWorkTime> GetTeamWorkTimeData(string prefix, DateTime startTime)
        {
            try
            {
                // 获得所有变量的变量名
                string varTeam = string.Format("{0}{1}", JCJName, prefix.Substring(2));
                //string strVar = "";
                //foreach (string var in TeamVariableList)
                //{
                //    strVar += string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                //}
                //string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), "0000-00-00 00:00:00:000");
                //log.WriteEntry(string.Format("班组{0} 时间段 {1} - {2}.", varTeam, startTime, DateTime.Now));
                int minCount = int.MaxValue;
                //Dictionary<string, List<string>> varDic = GetWINCCVariableList(query, TeamVariableList, ref minCount);
                Dictionary<string, List<string>> varDic = GetWINCCVariableList2(VariableType.TeamType, varTeam, prefix, TeamVariableList, startTime, DateTime.UtcNow, ref minCount);
                if (varDic == null || varDic.Count == 0)
                {
                    //log.WriteEntry(string.Format("班组{0}的记录为空。", prefix));
                    return null;
                }
                else if (varDic.Count != TeamVariableList.Length + 1) // 加1为Time变量
                {
                    string msg = string.Format("班组{2}获取的变量数'{0}'和变量列表数'{1}'不匹配! 最小变量总数{3}", varDic.Count, TeamVariableList.Length, varTeam, minCount);
                    string var = "";
                    foreach (KeyValuePair<string, List<string>> item in varDic)
                    {
                        var += string.Format("{0}\r\n", item.Key);
                    }
                    var += "\r\n";
                    foreach (string item in TeamVariableList)
                    {
                        var += string.Format("{0}\r\n", item);
                    }
                    log.WriteEntry(msg + "\r\n" + var, EventLogEntryType.Error);
                    return null;
                }

                // 记录工作人员信息
                string mesg = string.Format("班组变量数{0}, 班组数{1}, 生产线前缀{2}", varDic.Count, minCount, prefix);
                //log.WriteEntry(mesg);
                List<TeamWorkTime> retList = TeamWorkTime.Convert2TeamWorkTime(varDic, minCount);
                return retList;
            }
            catch (OleDbException ex)
            {
                string msg = string.Format("WinCCDataProcess.GetTeamWorkTimeData() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }
        #endregion

        private Dictionary<string, List<string>> GetWINCCVariableList(string query, string[] VariableList, ref int minCount)
        {
            OleDbCommand command = null;
            OleDbDataReader reader = null;
            try
            {
                Dictionary<string, List<string>> varDic = new Dictionary<string, List<string>>();
                List<string> valueList = new List<string>();    // 记录变量值列表
                List<DateTime> timeList = new List<DateTime>(); // 记录时间列表
                string varName = VariableList[0];    // 变量名, 也是变量列表的关键字
                using (command = new OleDbCommand(query, this.conn))
                {
                    reader = command.ExecuteReader();
                    bool firstListFinished = false; // 判断第一个变量列表是否读取完毕
                    DateTime? lastRecordTime = null; // 记录上一次的时间
                    int count = 0;
                    while (reader.Read())
                    {
                        DateTime tmpTime = reader.GetDateTime(1).ToLocalTime();
                        if (lastRecordTime == null) // 初始化上一次的记录时间
                        {
                            lastRecordTime = tmpTime;
                        }
                        // 如果这次的时间小于上次记录的时间， 说明这是另一个变量的记录数据
                        if (DateTime.Compare((DateTime)lastRecordTime, tmpTime) > 0)
                        {
                            firstListFinished = true;
                            if (timeList.Count > 0)  // 将时间列表记录到关键字Time中
                            {
                                List<string> copyTimeList = new List<string>();
                                foreach (DateTime time in timeList)
                                {
                                    copyTimeList.Add(time.ToString());
                                }
                                timeList.Clear();
                                varDic.Add("Time", copyTimeList);
                            }
                            if (valueList.Count > 0)    // 将值列表记录到变量值的关键字中
                            {
                                minCount = minCount > valueList.Count ? valueList.Count : minCount;
                                //string msg = string.Format("变量名：{2}, 变量数:{0}, 最小数:{1}", valueList.Count, minCount, varName);
                                //log.WriteEntry(msg);
                                List<string> copyVarList = new List<string>();
                                foreach (string item in valueList)
                                {
                                    copyVarList.Add(item);
                                }
                                valueList.Clear();
                                varDic.Add(varName, copyVarList);
                                //string msg = string.Format("变量：{0}, 列表数：{1}", varName, copyVarList.Count);
                                //log.WriteEntry(msg);
                            }
                            varName = VariableList[++count];
                        }

                        // 时间列表只需要记录一组变量值的就可以， 所以当第一个变量列表读取完时，
                        // 就不需要再记录时间列表了
                        if (firstListFinished == false)
                        {
                            timeList.Add(tmpTime);
                        }
                        valueList.Add(reader["RealValue"].ToString()); // 始终记录当前变量值
                        lastRecordTime = tmpTime;   // 记录上一次的时间
                    }
                    if (!reader.IsClosed)
                    {
                        //if (count == 0)
                        //{
                        //    string msg = string.Format("读取变量失败，读取命令：{0}", query);
                        //    log.WriteEntry(msg);
                        //}
                        reader.Close();
                    }
                }

                // 如果时间里面还有记录，说明当前只查询一个变量
                if (timeList.Count > 0)
                {
                    List<string> copyTimeList = new List<string>();
                    foreach (DateTime time in timeList)
                    {
                        copyTimeList.Add(time.ToString());
                    }
                    timeList.Clear();
                    varDic.Add("Time", copyTimeList);
                }
                // 记录剩余的变量值
                if (valueList.Count > 0)
                {
                    minCount = minCount > valueList.Count ? valueList.Count : minCount;
                    List<string> copyVarList = new List<string>();
                    foreach (string item in valueList)
                    {
                        copyVarList.Add(item);
                    }
                    valueList.Clear();
                    varDic.Add(varName, copyVarList);
                    //string msg = string.Format("变量：{0}, 列表数：{1}", varName, copyVarList.Count);
                    //log.WriteEntry(msg);
                }
                return varDic;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                if (command != null)
                    command.Dispose();
                string msg = string.Format("WinCCDataProcess.GetWINCCVariableList() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }

        private Dictionary<string, List<string>> GetWINCCVariableList2(VariableType varType, string varTeam, string prefix, string[] VariableList, 
            DateTime startTime, DateTime stopTime, ref int minCount)
        {
            OleDbCommand command = null;
            OleDbDataReader reader = null;
            Dictionary<string, List<string>> varDic = new Dictionary<string, List<string>>();
            List<string> timeList = new List<string>();
            List<string> unreadList = new List<string>();
            try
            {
                minCount = int.MaxValue;
                bool timeExist = false;
                foreach (string var in VariableList)
                {
                    int count = 0;
                    bool hasExist = false;
                    string strVar = string.Format("'{0}\\{1}_{2}';", varTeam, prefix, var);
                    string query = string.Format("TAG:R,({0}),'{1}','{2}'", strVar, startTime.ToString("yyyy-MM-dd HH:mm:ss:fff"), stopTime.ToString("yyyy-MM-dd HH:mm:ss:fff"));
                    using (command = new OleDbCommand(query, this.conn))
                    {
                        reader = command.ExecuteReader();
                        varDic.Add(var, new List<string>());
                        while (reader.Read())
                        {
                            // 记录时间列表
                            if (!timeExist)
                                timeList.Add(reader.GetDateTime(1).ToLocalTime().ToString());
                            hasExist = true;
                            // 记录变量值
                            varDic[var].Add(reader["RealValue"].ToString());
                            count++;
                        }
                        if (!timeExist && timeList.Count > 0)
                        {
                            varDic.Add("Time", timeList);
                            timeExist = true;
                        }
                        // 将不能读取到的变量存入列表中
                        if (!hasExist)
                            unreadList.Add(var);
                        else
                            minCount = minCount > count ? count : minCount;
                        reader.Close();
                    }
                }

                // 如果不能读取的变量数等于要读取的，那么有可能说明当前的时间段内没有记录任何变量
                if (unreadList.Count == VariableList.Length)
                {
                    return null;
                }
                // 有个别的变量读取不到, 从DB中拿去上一次记录的变量值填入到这次未读取的变量中
                else if(unreadList.Count > 0)
                {
                    if (!AddVariableFromDB(varType, prefix, unreadList, minCount, ref varDic))
                    {
                        log.WriteEntry("在从DB中读取原始记录变量时失败", System.Diagnostics.EventLogEntryType.Error);
                        return null;
                    }
                }

                // 将新的变量列表保存在DB中
                UpdateVariableListToDB(varType, prefix, minCount, varDic);                

                return varDic;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                if (command != null)
                    command.Dispose();
                string msg = string.Format("WinCCDataProcess.GetWINCCVariableList2() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return null;
            }
        }

        private bool AddVariableFromDB(VariableType varType, string prefix, List<string> unreadList, int minCount, ref Dictionary<string, List<string>> varDic)
        {
            SqlConnection sqlconn = new SqlConnection();
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                string servername = ConfigurationManager.ConnectionStrings["SQLServerName"].ConnectionString;
                string dbname = ConfigurationManager.ConnectionStrings["SQLCCDBName"].ConnectionString;
                string userid = ConfigurationManager.ConnectionStrings["SQLUserID"].ConnectionString;
                string pwd = ConfigurationManager.ConnectionStrings["SQLPassWord"].ConnectionString;
                sqlconn.ConnectionString = string.Format("Data Source={0};Initial Catalog={1};User Id={2};Password={3};", servername, dbname, userid, pwd);
                sqlconn.Open();
                string sql = "";
                switch(varType)
                {
                    case VariableType.JCJSummaryType:
                        sql = string.Format(GET_JCJSUMMARY_VARLIST, prefix);
                        break;
                    case VariableType.JCJDetailType:
                        sql = string.Format(GET_JCJDETAIL_VARLIST, prefix);
                        break;
                    case VariableType.JHJDataType:
                        sql = string.Format(GET_JHJDATA_VARLIST, prefix);
                        break;
                    case VariableType.TeamType:
                        sql = string.Format(GET_TEAM_VARLIST, prefix);
                        break;
                    case VariableType.WaitingOrderType:
                        sql = string.Format(GET_WAITINGORDER_VARLIST, prefix);
                        break;
                    default:
                        return false;
                }
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    if (reader.Read())
                    {
                        // 取出未读取的变量
                        foreach(string var in unreadList)
                        {
                            string varValue = reader[var].ToString();
                            for (int i = 0; i < minCount; i++)
                                varDic[var].Add(varValue);
                        }
                    }
                    reader.Close();
                }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.AddVariableFromDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
            finally
            {
                if (sqlconn.State != System.Data.ConnectionState.Closed)
                    sqlconn.Close();
            }
        }

        private bool UpdateVariableListToDB(VariableType varType, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlConnection sqlconn = new SqlConnection();
            try
            {
                string servername = ConfigurationManager.ConnectionStrings["SQLServerName"].ConnectionString;
                string dbname = ConfigurationManager.ConnectionStrings["SQLCCDBName"].ConnectionString;
                string userid = ConfigurationManager.ConnectionStrings["SQLUserID"].ConnectionString;
                string pwd = ConfigurationManager.ConnectionStrings["SQLPassWord"].ConnectionString;
                sqlconn.ConnectionString = string.Format("Data Source={0};Initial Catalog={1};User Id={2};Password={3};", servername, dbname, userid, pwd);
                sqlconn.Open();
                switch (varType)
                {
                    case VariableType.JCJSummaryType:
                        return UpdateJCJSummaryVariableListToDB(sqlconn, prefix, minCount, varDic);
                    case VariableType.JCJDetailType:
                        return UpdateJCJDetailVariableListToDB(sqlconn, prefix, minCount, varDic);
                    case VariableType.JHJDataType:
                        return UpdateJHJDataVariableListToDB(sqlconn, prefix, minCount, varDic);
                    case VariableType.TeamType:
                        return UpdateTeamVariableListToDB(sqlconn, prefix, minCount, varDic);
                    case VariableType.WaitingOrderType:
                        return UpdateWaitingOrderVariableListToDB(sqlconn, prefix, minCount, varDic);
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
                string msg = string.Format("WinCCDataProcess.UpdateVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
            finally
            {
                if (sqlconn.State != System.Data.ConnectionState.Closed)
                    sqlconn.Close();
            }
        }

        private bool UpdateJCJSummaryVariableListToDB(SqlConnection sqlconn, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                if (JCSummaryVariableList.Length != varDic.Count - 1)
                {
                    log.WriteEntry("UpdateJCJSummaryVariableListToDB写入变量和定义变量的数量不一致", System.Diagnostics.EventLogEntryType.Error);
                    return false;
                }
                string sql = string.Format(DELETE_JCJSUMMARY_VARIABLE, prefix);
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    cmd.ExecuteNonQuery(); 
                }

                sql = string.Format(INSERT_JCJSUMMARY_VARIABLE, prefix, varDic[JCSummaryVariableList[0]][minCount - 1], varDic[JCSummaryVariableList[1]][minCount - 1], varDic[JCSummaryVariableList[2]][minCount - 1],
                    varDic[JCSummaryVariableList[3]][minCount - 1], varDic[JCSummaryVariableList[4]][minCount - 1], varDic[JCSummaryVariableList[5]][minCount - 1], varDic[JCSummaryVariableList[6]][minCount - 1],
                    varDic[JCSummaryVariableList[7]][minCount - 1], varDic[JCSummaryVariableList[8]][minCount - 1], varDic[JCSummaryVariableList[9]][minCount - 1], varDic[JCSummaryVariableList[10]][minCount - 1],
                    varDic[JCSummaryVariableList[11]][minCount - 1], varDic[JCSummaryVariableList[12]][minCount - 1], varDic[JCSummaryVariableList[13]][minCount - 1], varDic[JCSummaryVariableList[14]][minCount - 1],
                    varDic[JCSummaryVariableList[15]][minCount - 1], varDic[JCSummaryVariableList[16]][minCount - 1], varDic[JCSummaryVariableList[17]][minCount - 1], varDic[JCSummaryVariableList[18]][minCount - 1],
                    varDic[JCSummaryVariableList[19]][minCount - 1], varDic[JCSummaryVariableList[20]][minCount - 1], varDic[JCSummaryVariableList[21]][minCount - 1], varDic[JCSummaryVariableList[22]][minCount - 1],
                    varDic[JCSummaryVariableList[23]][minCount - 1], varDic[JCSummaryVariableList[24]][minCount - 1], varDic[JCSummaryVariableList[25]][minCount - 1], varDic[JCSummaryVariableList[26]][minCount - 1],
                    varDic[JCSummaryVariableList[27]][minCount - 1], varDic[JCSummaryVariableList[28]][minCount - 1], varDic[JCSummaryVariableList[29]][minCount - 1], varDic[JCSummaryVariableList[30]][minCount - 1],
                    varDic[JCSummaryVariableList[31]][minCount - 1], varDic[JCSummaryVariableList[32]][minCount - 1], varDic[JCSummaryVariableList[33]][minCount - 1], varDic[JCSummaryVariableList[34]][minCount - 1],
                    varDic[JCSummaryVariableList[35]][minCount - 1], varDic[JCSummaryVariableList[36]][minCount - 1], varDic[JCSummaryVariableList[37]][minCount - 1], varDic[JCSummaryVariableList[38]][minCount - 1],
                    varDic[JCSummaryVariableList[39]][minCount - 1], varDic[JCSummaryVariableList[40]][minCount - 1], varDic[JCSummaryVariableList[41]][minCount - 1], varDic[JCSummaryVariableList[42]][minCount - 1],
                    varDic[JCSummaryVariableList[43]][minCount - 1]);
                using (cmd = new SqlCommand(sql, sqlconn))
                { cmd.ExecuteNonQuery(); }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.UpdateJCJSummaryVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
        }
        private bool UpdateJCJDetailVariableListToDB(SqlConnection sqlconn, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                if (JCDetailVariableList.Length != varDic.Count - 1)
                {
                    log.WriteEntry("UpdateJCJDetailVariableListToDB写入变量和定义变量的数量不一致", System.Diagnostics.EventLogEntryType.Error);
                    return false;
                }

                string sql = string.Format(DELETE_JCJDETAIL_VARIABLE, prefix);
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    cmd.ExecuteNonQuery(); 
                }

                sql = string.Format(INSERT_JCJDETAIL_VARIABLE, prefix, varDic[JCDetailVariableList[0]][minCount - 1], varDic[JCDetailVariableList[1]][minCount - 1], varDic[JCDetailVariableList[2]][minCount - 1],
                    varDic[JCDetailVariableList[3]][minCount - 1], varDic[JCDetailVariableList[4]][minCount - 1], varDic[JCDetailVariableList[5]][minCount - 1], varDic[JCDetailVariableList[6]][minCount - 1],
                    varDic[JCDetailVariableList[7]][minCount - 1], varDic[JCDetailVariableList[8]][minCount - 1], varDic[JCDetailVariableList[9]][minCount - 1], varDic[JCDetailVariableList[10]][minCount - 1],
                    varDic[JCDetailVariableList[11]][minCount - 1], varDic[JCDetailVariableList[12]][minCount - 1], varDic[JCDetailVariableList[13]][minCount - 1], varDic[JCDetailVariableList[14]][minCount - 1],
                    varDic[JCDetailVariableList[15]][minCount - 1], varDic[JCDetailVariableList[16]][minCount - 1], varDic[JCDetailVariableList[17]][minCount - 1], varDic[JCDetailVariableList[18]][minCount - 1],
                    varDic[JCDetailVariableList[19]][minCount - 1], varDic[JCDetailVariableList[20]][minCount - 1], varDic[JCDetailVariableList[21]][minCount - 1], varDic[JCDetailVariableList[22]][minCount - 1],
                    varDic[JCDetailVariableList[23]][minCount - 1], varDic[JCDetailVariableList[24]][minCount - 1]);
                using (cmd = new SqlCommand(sql, sqlconn))
                { cmd.ExecuteNonQuery(); }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.UpdateJCJDetailVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
        }
        private bool UpdateJHJDataVariableListToDB(SqlConnection sqlconn, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                if (JHVariableList.Length != varDic.Count - 1)
                {
                    log.WriteEntry("UpdateJHJDataVariableListToDB写入变量和定义变量的数量不一致", System.Diagnostics.EventLogEntryType.Error);
                    return false;
                }

                string sql = string.Format(DELETE_JHJDATA_VARIABLE, prefix);
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    cmd.ExecuteNonQuery(); 
                }

                sql = string.Format(INSERT_JHJDATA_VARIABLE, prefix, varDic[JHVariableList[0]][minCount - 1], varDic[JHVariableList[1]][minCount - 1], varDic[JHVariableList[2]][minCount - 1],
                    varDic[JHVariableList[3]][minCount - 1], varDic[JHVariableList[4]][minCount - 1], varDic[JHVariableList[5]][minCount - 1], varDic[JHVariableList[6]][minCount - 1],
                    varDic[JHVariableList[7]][minCount - 1], varDic[JHVariableList[8]][minCount - 1], varDic[JHVariableList[9]][minCount - 1], varDic[JHVariableList[10]][minCount - 1],
                    varDic[JHVariableList[11]][minCount - 1], varDic[JHVariableList[12]][minCount - 1], varDic[JHVariableList[13]][minCount - 1], varDic[JHVariableList[14]][minCount - 1],
                    varDic[JHVariableList[15]][minCount - 1], varDic[JHVariableList[16]][minCount - 1], varDic[JHVariableList[17]][minCount - 1], varDic[JHVariableList[18]][minCount - 1]);
                using (cmd = new SqlCommand(sql, sqlconn))
                { cmd.ExecuteNonQuery(); }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.UpdateJHJDataVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
        }
        private bool UpdateTeamVariableListToDB(SqlConnection sqlconn, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                if (TeamVariableList.Length != varDic.Count - 1)
                {
                    log.WriteEntry("UpdateTeamVariableListToDB写入变量和定义变量的数量不一致", System.Diagnostics.EventLogEntryType.Error);
                    return false;
                }

                string sql = string.Format(DELETE_TEAM_VARIABLE, prefix);
                using (cmd = new SqlCommand(sql, sqlconn))
                { cmd.ExecuteNonQuery(); }

                sql = string.Format(INSERT_TEAM_VARIABLE, prefix, varDic[TeamVariableList[0]][minCount - 1], varDic[TeamVariableList[1]][minCount - 1], varDic[TeamVariableList[2]][minCount - 1],
                    varDic[TeamVariableList[3]][minCount - 1], varDic[TeamVariableList[4]][minCount - 1], varDic[TeamVariableList[5]][minCount - 1], varDic[TeamVariableList[6]][minCount - 1],
                    varDic[TeamVariableList[7]][minCount - 1], varDic[TeamVariableList[8]][minCount - 1], varDic[TeamVariableList[9]][minCount - 1], varDic[TeamVariableList[10]][minCount - 1]);
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    cmd.ExecuteNonQuery();
                }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.UpdateTeamVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
        }
        private bool UpdateWaitingOrderVariableListToDB(SqlConnection sqlconn, string prefix, int minCount, Dictionary<string, List<string>> varDic)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                if (WaitingVarList.Length != varDic.Count - 1)
                {
                    log.WriteEntry("UpdateWaitingOrderVariableListToDB写入变量和定义变量的数量不一致", System.Diagnostics.EventLogEntryType.Error);
                    return false;
                }

                string sql = string.Format(DELETE_WAITINGORDER_VARIABLE, prefix);
                using (cmd = new SqlCommand(sql, sqlconn))
                {
                    cmd.CommandTimeout = 0;
                    cmd.ExecuteNonQuery();
                }

                sql = string.Format(INSERT_WAITINGORDER_VARIABLE, prefix, varDic[WaitingVarList[0]][minCount - 1], varDic[WaitingVarList[1]][minCount - 1], varDic[WaitingVarList[2]][minCount - 1],
                    varDic[WaitingVarList[3]][minCount - 1], varDic[WaitingVarList[4]][minCount - 1], varDic[WaitingVarList[5]][minCount - 1]);
                using (cmd = new SqlCommand(sql, sqlconn))
                { cmd.ExecuteNonQuery(); }
                return true;
            }
            catch (Exception ex)
            {
                if (reader != null && !reader.IsClosed)
                    reader.Close();
                //if (cmd != null)
                    //cmd.Dispose();
                string msg = string.Format("WinCCDataProcess.UpdateWaitingOrderVariableListToDB() Failed: {0}.\r\nDetail: {1}", ex.Message, ex.StackTrace);
                log.WriteEntry(msg, System.Diagnostics.EventLogEntryType.Error);
                return false;
            }
        }

        private DateTime GetStopTime(DateTime startTime, DateTime nowTime)
        {
            TimeSpan span = (TimeSpan)(nowTime - startTime);
            double daySec = span.TotalSeconds;
            if (daySec > DaySeconds)
                return startTime.AddSeconds(DaySeconds);
            else
                return startTime.AddSeconds(daySec);
        }
    }
}
